#include "epollServer.hpp"
#include "SetDaemon.hpp"
#include "Business.hpp"
#include <cmath>

void Format(const char *str)
{
    // [ip]意思是可有可无，没有则默认绑定0.0.0.0号ip
    std::cout << "Format: " << str << "  [ip]  port" << std::endl;
    exit(3);
}

// 通用业务处理函数 -- 上层业务和下层网络分离解耦
void GeneralServices(Connection *connect, string &message, service_func sf)
{
    // Debug
    const unordered_map<int, string>& tmp = connect->GetepollServerThis()->GetUserInetWorkData();
    cout << "Client[" << tmp.at(connect->Getfd()) << "]#" << message  << endl;

    // 1.反序列化 -- 接受到的数据是请求类序列化后的值
    Protocol::Requst req;
    if (req.Deserialize(message) == false)
    {
        cout << "The request format is incorrect! ! ! -- Close Connection" << endl;
        connect->GetExcepEvent()(connect);
    }
    
    // 2.构建响应报文
    Protocol::Reponse rep;
    sf(&rep, req); // 业务处理
    string sendData;
    rep.Serialize(&sendData);

    sendData += '\n'; // Debug

    // 3.序列化后的数据拷贝到outbuffer缓冲区中
    connect->GetOutbuffer() += sendData;
    cout << "Server send: " << sendData << endl;
    // 4.把读写事件就绪打开 -- 后续会自动调用读写事件就绪方法 -- 读写事件派发 -- 处理写事件第一种版本
    // connect->GetepollServerThis()->EnableReadWrite(connect->Getfd(), true, true);

    // 4. 第二版本 -- 高效率版本 --直接发送 -- 如果没发完就设置写事件就绪方法，写完了可以不做也可以重新设置读事件就绪
    connect->GetSendEvent()(connect);
    if (connect->GetOutbuffer().empty() == true)
    {
        connect->GetepollServerThis()->EnableReadWrite(connect->Getfd(), true, false); // 清空则去除写事件监听
    }
    else
    {
        connect->GetepollServerThis()->EnableReadWrite(connect->Getfd(), true, true); // 还有数据则增加读写事件监听
    }
}

// 构建响应报文并且send
int HandlerRequst(Connection *connect, string &message)
{
    GeneralServices(connect, message, Network_Computing);
}

int main(int argc, char *argv[])
{
    // Daemon(); // 部署服务器 -- 创建守护进程

    if (argc < 2)
        Format(argv[0]);

    string ip;
    uint16_t port;
    if (argc == 3)
    {
        ip = argv[1];
        port = std::stoi(argv[2]);
    }
    else if (argc == 2)
    {
        port = std::stoi(argv[1]);
    }

    EpollServer eps(HandlerRequst, port, ip);
    eps.InitEpollServer();
    eps.StartEpollServer();
    return 0;
}